//
// Created by guoshunw on 24-3-31.
//

#ifndef CMAKE_HELLO_ENUM_TO_STRING_HELPER_H
#define CMAKE_HELLO_ENUM_TO_STRING_HELPER_H

#include "iostream"
#include "log.h"
#include "thread"
#include "unordered_map"


template<typename T, std::enable_if_t<std::is_enum_v<T>, int> = 0>
const std::unordered_map<T, const char *> &GetEnumMap() {
    static const std::unordered_map<T, const char *> OMX_EnumMap = {};
    LOGI << "Call " << __PRETTY_FUNCTION__;
    return OMX_EnumMap;
}


template<typename T, std::enable_if_t<std::is_enum_v<T>, int> = 0>
const char *GetEnumName(T err, bool want_underlying_value = false) {
    static auto OMX_EnumMap = GetEnumMap<T>();
    static thread_local std::string str_val;
    auto val = static_cast<std::underlying_type_t<T>>(err);

    auto itr = OMX_EnumMap.find(err);
    if (itr != OMX_EnumMap.end()) {
        str_val = itr->second;

        if (want_underlying_value) {
            std::stringstream oos;
            oos << itr->second << "(" << std::hex << std::showbase << val << ")";
            str_val = oos.str();
        }
        return str_val.c_str();
    }

    std::stringstream oos;
    oos << "Unknown(" << std::hex << std::showbase << val << ")";
    str_val = oos.str();
    return str_val.c_str();
}

#define ENUM_V_(val) \
    { val, #val }

#define GENERATE_ENUM_MAP(TYPE, ...)                                         \
    template<>                                                            \
    const std::unordered_map<TYPE, const char *> &GetEnumMap() {             \
        static const std::unordered_map<TYPE, const char *> &OMX_EnumMap = { \
                __VA_ARGS__};                                                \
        return OMX_EnumMap;                                                  \
    }


#define GENERATE_ENUM_MAP_DECLARE(TYPE) template<> \
const std::unordered_map<TYPE, const char *> &GetEnumMap();

// template specialization for enum to string needs to be in the same compiling unit to take effect
#include "enum_to_string.h"

#endif//CMAKE_HELLO_ENUM_TO_STRING_HELPER_H
